home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / plnk081.zip / pilot-link.0.8.1 / pilot-debug.c < prev    next >
C/C++ Source or Header  |  1997-08-03  |  53KB  |  1,931 lines

  1. /* pilot-debug.c:  Pilot debugging console, with optional graphics support
  2.  *
  3.  * This is free software, licensed under the GNU Public License V2.
  4.  * See the file COPYING for details.
  5.  *
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <unistd.h>
  11. #include <signal.h>
  12. #include <sys/time.h>
  13. #include <sys/types.h>
  14. #include "pi-source.h"
  15. #include "pi-socket.h"
  16. #include "pi-dlp.h"
  17. #include "pi-syspkt.h"
  18.  
  19. /* Definitions for functions in pd-tty.c */
  20.  
  21. extern void do_readline(void);
  22.  
  23. /* Display text asynchronously, and make sure it doesn't interfere with
  24.    the current prompt */
  25. extern void display(char * text, char * tag, int type);
  26.  
  27. #ifndef LIBDIR
  28. # define LIBDIR "."
  29. #endif
  30.  
  31. #ifdef TK
  32. int usetk;
  33. # include <tk.h>
  34. #else
  35. # include <tcl.h>
  36. #endif
  37.  
  38. #ifndef TCL_ACTIVE
  39. # define TCL_ACTIVE TCL_READABLE
  40. #endif
  41. #ifndef TCL_RELEASE_LEVEL
  42. # define TCL_RELEASE_LEVEL 2
  43. #endif
  44.  
  45. /*
  46.  * The following variable is a special hack that is needed in order for
  47.  * Sun shared libraries to be used for Tcl.
  48.  */
  49.  
  50. extern int matherr();
  51. int *tclDummyMathPtr = (int *) matherr;
  52.  
  53. int done = 0;
  54.  
  55. int Interactive = 1;
  56.  
  57. Tcl_Interp * interp;        
  58. struct Pilot_state state;
  59.  
  60. int debugger = 0; /* If non-zero, then debugger is thought to be active */
  61. int console = 0;  /* If non-zero, then console is thought to be active 
  62.                      Note: if both console and debugger are thought to be
  63.                            active, only the debugger will be usable. If
  64.                            execution is continued, the console be
  65.                            be usable again. */
  66. int stalestate = 1; /* If non-zero, then the current Pilot state (in particular the registers)
  67.                        should be assumed out-of-date */
  68.                        
  69. int port = 0;
  70.  
  71.  
  72. int tty;            /* Non-zero means standard input is a
  73.                  * terminal-like device.  Zero means it's*/
  74.  
  75.  
  76. /* Misc utility */
  77. void SetLabel(const char * label, const char * value)
  78. {
  79. #ifdef TK
  80.   if (usetk)
  81.     Tcl_VarEval(interp, label, " configure -text \"", value, "\"",NULL);
  82. #endif
  83. }
  84.  
  85. char * itoa(int val) {
  86.   static char buf[20];
  87.   sprintf(buf,"%d",val);
  88.   return buf;
  89. }
  90.  
  91. char * htoa(int val) {
  92.   static char buf[9];
  93.   sprintf(buf,"%8.8X",val);
  94.   return buf;
  95. }
  96.  
  97. char * h4toa(int val) {
  98.   static char buf[5];
  99.   sprintf(buf,"%4.4X",val);
  100.   return buf;
  101. }
  102.  
  103. int SayInteractive(char * text)
  104. {
  105.     Tcl_DString d;
  106.     
  107.     if (!Interactive)
  108.       return 0;
  109.     
  110.     Tcl_DStringInit(&d);
  111.  
  112. #ifdef TK
  113.     if (usetk) {
  114.         Tcl_DStringAppendElement(&d, ".f.t");
  115.         Tcl_DStringAppendElement(&d, "insert");
  116.         Tcl_DStringAppendElement(&d, "insert");
  117.         Tcl_DStringAppendElement(&d, text);
  118.         Tcl_Eval(interp, Tcl_DStringValue(&d));
  119.         Tcl_DStringFree(&d);
  120.         Tcl_DStringAppendElement(&d, ".f.t");    
  121.         Tcl_DStringAppendElement(&d, "see");
  122.         Tcl_DStringAppendElement(&d, "insert");
  123.         Tcl_Eval(interp, Tcl_DStringValue(&d));
  124.         Tcl_DStringFree(&d);
  125.     } else {
  126. #endif
  127.         Tcl_DStringAppendElement(&d, "puts");
  128.         Tcl_DStringAppendElement(&d, text);
  129.         Tcl_Eval(interp, Tcl_DStringValue(&d));
  130.         Tcl_DStringFree(&d);
  131.  
  132. #ifdef TK
  133.     }
  134. #endif
  135.     Tcl_Eval(interp, Tcl_DStringValue(&d));
  136.     Tcl_DStringFree(&d);
  137.     
  138.     return 0;
  139. }
  140.  
  141. int Say(char * text)
  142. {
  143.     Tcl_DString d;
  144.     
  145.     if (Interactive) {
  146.         Tcl_DStringInit(&d);
  147. #ifdef TK
  148.         if (usetk) {
  149.             Tcl_DStringAppendElement(&d, ".f.t");
  150.             Tcl_DStringAppendElement(&d, "insert");
  151.             Tcl_DStringAppendElement(&d, "insert");
  152.             Tcl_DStringAppendElement(&d, text);
  153.             Tcl_Eval(interp, Tcl_DStringValue(&d));
  154.             Tcl_DStringFree(&d);
  155.             Tcl_DStringAppendElement(&d, ".f.t");    
  156.             Tcl_DStringAppendElement(&d, "see");
  157.             Tcl_DStringAppendElement(&d, "insert");
  158.             Tcl_Eval(interp, Tcl_DStringValue(&d));
  159.             Tcl_DStringFree(&d);
  160.         } else {
  161. #endif
  162.             Tcl_DStringAppendElement(&d, "puts");
  163.             Tcl_DStringAppendElement(&d, text);
  164.             Tcl_Eval(interp, Tcl_DStringValue(&d));
  165.             Tcl_DStringFree(&d);
  166.  
  167. #ifdef TK
  168.         }
  169. #endif
  170.     } else 
  171.             Tcl_AppendResult(interp, text, NULL);
  172.     
  173.     return 0;
  174. }
  175.  
  176. int Error(char * text)
  177. {
  178.     Tcl_SetResult(interp, text, TCL_STATIC);
  179.     return TCL_ERROR;
  180. }
  181.  
  182. void SetModeLabel(void)
  183. {
  184.   SetLabel(".state.halted",debugger ? "Debugger" :
  185.                            console ? "Console" :
  186.                            "None");
  187. }
  188.  
  189.  
  190. /* Workhorse function to read input from the Pilot. Called both via Tcl event loop on serial input,
  191.    and explicitly by any function has thinks there should be a packet ready. */
  192.    
  193. void Read_Pilot(ClientData clientData, int mask) {
  194.   unsigned char buf[4096];
  195.   int l;
  196.   
  197.   memset(buf,0,4096);
  198.   l = pi_read(port, buf, 4096);
  199.   
  200.   if (l < 6)
  201.     return;
  202.  
  203.   /*puts("From Pilot:");
  204.   dumpdata((unsigned char *)buf, l);*/
  205.   
  206.   if(buf[2] == 0) { /* SysPkt command */
  207.     if(buf[0] == 2) { /* UI */
  208.       if ((!console) || debugger) {
  209.               Say("Console active\n");
  210.           console = 1;
  211.           debugger = 0;
  212.           SetModeLabel();
  213.           Tcl_VarEval(interp, "checkin 25",NULL);
  214.       }
  215.       if(buf[4] == 0x0c) { /* Screen update */
  216. #ifdef TK
  217.     if (usetk) {
  218.           int i, x1, y1, sx, sy, w, h, bytes;
  219.           int y,x;
  220.           char buffer[8192];
  221.         Tk_PhotoImageBlock block;
  222.         Tk_PhotoHandle handle;
  223.           
  224.           bytes = get_short(buf+6);
  225.           y1 = get_short(buf+8);
  226.           x1 = get_short(buf+10);
  227.           sy = get_short(buf+12);
  228.           sx = get_short(buf+14);
  229.           h = get_short(buf+16);
  230.           w = get_short(buf+18);
  231.           
  232.         block.width = w+x1;
  233.         block.height =h;
  234.         block.pitch = w+x1;
  235.         block.pixelSize = 1;
  236.         block.offset[0] = 0;
  237.         block.offset[1] = 0;
  238.         block.offset[2] = 0; 
  239.         block.pixelPtr = buffer;
  240.    
  241.         handle = Tk_FindPhoto("Case");
  242.  
  243.         i = 0;
  244.         l = 0;
  245.         for (y=0;y<h;y++) {
  246.           l = 20 + (y*bytes);
  247.           for(x=0;x<(w+x1);x++) {
  248.             int mask = 1<<(7-(x%8));
  249.             buffer[i++] = (buf[x/8+l] & mask) ? 0 : 0xff;
  250.           }
  251.         }
  252.       
  253.         /*for(i=0;i<((l-20)*8);i++) {
  254.              int p = i/8+20;
  255.              int b = 1<<(7-(i%8));
  256.               buffer[i] = (buf[p] & b) ? 0 : 0xff;
  257.         }*/
  258.         Tk_PhotoPutBlock(handle, &block, 32+sx-x1, 33+sy-y1, w+x1, h);
  259.       
  260.         Tcl_VarEval(interp, "global show; set show(.remote) 1; update", NULL);
  261.         }
  262. #endif           
  263.     return;
  264.       }
  265.       
  266.     } else if(buf[0] == 1) { /* Console */
  267.       if(buf[4] == 0x7f) { /* Message from Pilot */
  268.           int i;
  269.         
  270.           for(i=6;i<l;i++)
  271.             if(buf[i] == '\r')
  272.               buf[i] = '\n';          
  273.         /* Insert message into both debug and console windows */        
  274. #ifdef TK
  275.     if (usetk) {
  276.           Tcl_VarEval(interp,".console.t insert end \"",buf+6,"\"",NULL);
  277.           Tcl_VarEval(interp,".console.t mark set insert end",NULL);
  278.           Tcl_VarEval(interp,".console.t see insert",NULL);
  279.         }
  280. #endif
  281.     display(buf+6, "Console: ", 2);
  282.  
  283.         return;
  284.       }
  285.     } else if (buf[0] == 0) { /* Debug */
  286.       if (!debugger) {
  287.            debugger = 1;
  288.            SetModeLabel();
  289.        Tcl_VarEval(interp, "checkin 25",NULL);
  290.       }
  291.         if (buf[4] == 0x7f) { /* Message */
  292.           int i;
  293.           for(i=6;i<l;i++)
  294.               if(buf[i] == '\r')
  295.                 buf[i] = '\n';          
  296.  
  297.     display(buf+6, "Debug: ", 1);
  298.           
  299.           return;
  300.         }
  301.         else if (buf[4] == 0x8c) { /* Breakpoints set */
  302.            Say("Breakpoint set\n");
  303.            return;
  304.         }
  305.         else if (buf[4] == 0x80) { /* State response */
  306.         
  307.            sys_UnpackState(buf+6,&state);
  308.            
  309.            if (stalestate) {
  310.                char buffer[40];
  311.                sprintf(buffer, "Pilot halted at %8.8lX (function %s) with exception %d\n",
  312.                    state.regs.PC, state.func_name, state.exception);
  313.                display(buffer, "Debug: ", 1);
  314.                stalestate = 0;
  315.            }
  316.            
  317.            SetLabel(".state.exception",itoa(state.exception));
  318.            SetLabel(".state.funcname",state.func_name);
  319.            SetLabel(".state.funcstart",htoa(state.func_start));
  320.            SetLabel(".state.funcend",htoa(state.func_end));
  321.            SetLabel(".state.d0",htoa(state.regs.D[0]));
  322.            SetLabel(".state.a0",htoa(state.regs.A[0]));
  323.            SetLabel(".state.d1",htoa(state.regs.D[1]));
  324.            SetLabel(".state.a1",htoa(state.regs.A[1]));
  325.            SetLabel(".state.d2",htoa(state.regs.D[2]));
  326.            SetLabel(".state.a2",htoa(state.regs.A[2]));
  327.            SetLabel(".state.d3",htoa(state.regs.D[3]));
  328.            SetLabel(".state.a3",htoa(state.regs.A[3]));
  329.            SetLabel(".state.d4",htoa(state.regs.D[4]));
  330.            SetLabel(".state.a4",htoa(state.regs.A[4]));
  331.            SetLabel(".state.d5",htoa(state.regs.D[5]));
  332.            SetLabel(".state.a5",htoa(state.regs.A[5]));
  333.            SetLabel(".state.d6",htoa(state.regs.D[6]));
  334.            SetLabel(".state.a6",htoa(state.regs.A[6]));
  335.            SetLabel(".state.d7",htoa(state.regs.D[7]));
  336.  
  337.            SetLabel(".state.ssp",htoa(state.regs.SSP));
  338.            SetLabel(".state.usp",htoa(state.regs.USP));
  339.            SetLabel(".state.sr",h4toa(state.regs.SR));
  340.            SetLabel(".state.pc",htoa(state.regs.PC));
  341.  
  342.            SetLabel(".state.reset",state.reset ? "Yes" : "No");
  343.  
  344.            SetLabel(".state.b1",htoa(state.breakpoint[0].address));
  345.            SetLabel(".state.b1a",(state.breakpoint[0].enabled) ? "Yes" : "No");
  346.            SetLabel(".state.b2",htoa(state.breakpoint[1].address));
  347.            SetLabel(".state.b2a",(state.breakpoint[1].enabled) ? "Yes" : "No");
  348.            SetLabel(".state.b3",htoa(state.breakpoint[2].address));
  349.            SetLabel(".state.b3a",(state.breakpoint[2].enabled) ? "Yes" : "No");
  350.            SetLabel(".state.b4",htoa(state.breakpoint[3].address));
  351.            SetLabel(".state.b4a",(state.breakpoint[3].enabled) ? "Yes" : "No");
  352.            SetLabel(".state.b5",htoa(state.breakpoint[4].address));
  353.            SetLabel(".state.b5a",(state.breakpoint[4].enabled) ? "Yes" : "No");
  354.            SetLabel(".state.b6",htoa(state.breakpoint[5].address));
  355.            SetLabel(".state.b6a",(state.breakpoint[5].enabled) ? "Yes" : "No");
  356.            
  357.            /* Show the state window if it is hidden */
  358.            Tcl_VarEval(interp, "set show(.state) 1", NULL); 
  359.            return;
  360.         }
  361.     }
  362.   }
  363. }
  364.  
  365.  
  366.  
  367. /* Workhorse function to turn an address string into a numeric value. Ideally, it should
  368.    also know about traps, function names, etc. As it is, it just assumed the text is
  369.    a hexadecimal number, with or with '0x' prefix. */
  370. unsigned long ParseAddress(char * address) {
  371.     return strtoul(address, 0, 16);
  372. }
  373.  
  374. /* Utility function to modify breakpoint table */
  375. int SetBreakpoint(int bp, unsigned long address, int enabled) {
  376.  
  377.     state.breakpoint[bp].address = address;
  378.     state.breakpoint[bp].enabled = enabled;
  379.  
  380.         SetLabel(".state.b1",htoa(state.breakpoint[0].address));
  381.         SetLabel(".state.b1a",(state.breakpoint[0].enabled) ? "Yes" : "No");
  382.         SetLabel(".state.b2",htoa(state.breakpoint[1].address));
  383.         SetLabel(".state.b2a",(state.breakpoint[1].enabled) ? "Yes" : "No");
  384.         SetLabel(".state.b3",htoa(state.breakpoint[2].address));
  385.         SetLabel(".state.b3a",(state.breakpoint[2].enabled) ? "Yes" : "No");
  386.         SetLabel(".state.b4",htoa(state.breakpoint[3].address));
  387.         SetLabel(".state.b4a",(state.breakpoint[3].enabled) ? "Yes" : "No");
  388.         SetLabel(".state.b5",htoa(state.breakpoint[4].address));
  389.         SetLabel(".state.b5a",(state.breakpoint[4].enabled) ? "Yes" : "No");
  390.         SetLabel(".state.b6",htoa(state.breakpoint[5].address));
  391.         SetLabel(".state.b6a",(state.breakpoint[5].enabled) ? "Yes" : "No");
  392.         
  393.     
  394.     sys_SetBreakpoints(port, &state.breakpoint[0]);
  395.     
  396.     Read_Pilot(0, 0);
  397.     
  398.     return 0;
  399. }
  400.  
  401. /* Attempt to verify a connection to either the debugger or console */
  402. int DbgAttach(int verify)
  403. {
  404.   struct RPC_params p;
  405.   
  406.   if (!port) {
  407.     Error("No serial port selected, use 'port' command to choose one.\n");
  408.     return 0;
  409.   }
  410.  
  411. again:  
  412.   if (verify || (!debugger && !console)) {
  413.     int old = debugger;
  414.     sys_QueryState(port);
  415.     debugger = 0;
  416.     Read_Pilot(0,0);
  417.     if (debugger && !old)
  418.       if (verify > 1)
  419.         Say("Attaching to Pilot debugger\n");
  420.       else
  421.         SayInteractive("(attaching to Pilot debugger)\n");
  422.   }
  423.   
  424.   if (!debugger && (verify || !console)) {
  425.     int err;
  426.     int old = console;
  427.      console = 0;
  428.     PackRPC(&p, 0xA09E, RPC_IntReply, RPC_End); /* TaskID, a harmless call */
  429.     DoRPC(port, 1, &p, &err);
  430.     if (err == 0)
  431.       console = 1;
  432.     else 
  433.       console = 0;
  434.     if (console && !old)
  435.       if (verify > 1)
  436.         Say("Attaching to Pilot console\n");
  437.       else
  438.         SayInteractive("(attaching to Pilot console)\n");
  439.     
  440.   }
  441.   
  442.   if (!debugger && !console && !verify) {
  443.     verify = 1;
  444.     goto again;
  445.   }
  446.   
  447.   SetModeLabel();
  448.  
  449.   return (debugger || console);
  450. }
  451.  
  452. int DbgAttachDebugger(int verify)
  453. {
  454.   if (!port) {
  455.     Error("No serial port selected, use 'port' command to choose one.\n");
  456.     return 0;
  457.   }
  458.   
  459.   if (!debugger || verify) {
  460.     int old = debugger;
  461.     debugger = 0;
  462.     sys_QueryState(port);
  463.     Read_Pilot(0,0);
  464.     SetModeLabel();
  465.     if (debugger && !old)
  466.       SayInteractive("(attaching to Pilot debugger)\n");
  467.   }
  468.   
  469.   if (!debugger) {
  470.     Error("Unable to attach to debugger on Pilot. Is the Pilot connected and in debugging mode?\n");
  471.   }
  472.   return debugger;
  473. }
  474.  
  475. int DbgAttachConsole(int verify)
  476. {
  477.   int err;
  478.   struct RPC_params p;
  479.  
  480.   if (!port) {
  481.     Error("No serial port selected, use 'port' command to choose one.\n");
  482.     return 0;
  483.   }
  484.     
  485.   if (verify || debugger || !console) {
  486.     int old = console && !debugger;
  487.     PackRPC(&p, 0xA09E, RPC_IntReply, RPC_End); /* TaskID, a harmless call */
  488.     DoRPC(port, 1, &p, &err);
  489.     if (err == 0) {
  490.        console = 1;
  491.        debugger = 0;
  492.        SetModeLabel();
  493.     } else {
  494.       if (!debugger)
  495.         console = 0;
  496.     }
  497.     if ((console && !debugger) && !old)
  498.       SayInteractive("(attaching to Pilot console)\n");
  499.   }
  500.   
  501.   if (!console || debugger) {
  502.     Error("Unable to attach to console on Pilot. Is the Pilot connected, in console mode, and not in debugger mode?\n");
  503.   }
  504.   
  505.   return console;
  506. }
  507.  
  508. unsigned long DbgRPC(struct RPC_params * p, int * error)
  509. {
  510.     unsigned long result = 0;
  511.     int err = -1;
  512.  
  513.   if (!port) {
  514.     Error("No serial port selected, use 'port' command to choose one.\n");
  515.     return 0;
  516.   }
  517.       
  518.     if (p->reply == RPC_NoReply) {
  519.       /* If the RPC call will normally generate no reply (as in a call that reboots the machine)
  520.          then we need to do some special work to verify that the connection is active */
  521.       DbgAttach(1);
  522.       if (!debugger && !console) {
  523.         if (error)
  524.           *error = -1;
  525.         Error("Unable to invoke RPC on Pilot. Is the Pilot connected and in debugging or console mode?\n");
  526.         return 0;
  527.       }
  528.     }
  529.  
  530.     if (debugger) {
  531.         result = DoRPC(port, 0, p, &err);
  532.         if ((err < 0) && (p->reply != RPC_NoReply)) /* Failure, assume no response */ {
  533.             debugger = 0;
  534.             SetModeLabel();
  535.         }
  536.     } else if (console) {
  537.         result = DoRPC(port, 1, p, &err);
  538.         if ((err < 0) && (p->reply != RPC_NoReply)) /* Failure, assume no response */ {
  539.             console = 0;
  540.             SetModeLabel();
  541.         }
  542.     }/* else {
  543.         Say("(attaching to Pilot)\n");
  544.     }*/
  545.     
  546.     if (!console && !debugger) {
  547.         DbgAttach(0);
  548.         if (debugger) {
  549.             result = DoRPC(port, 0, p, &err);
  550.         } else if (console) {
  551.             result = DoRPC(port, 1, p, &err);
  552.         } else {
  553.             /* complete failure to attach */
  554.             Error("Unable to invoke RPC on Pilot. Is the Pilot connected and in debugging or console mode?\n");
  555.         }
  556.     }
  557.     
  558.     if (error)
  559.         *error = err;
  560.         
  561.     return result;
  562. }
  563.  
  564. unsigned char buffer[0xffff];
  565.  
  566.  
  567. /* Go, restart execution */
  568. int proc_g(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  569. {
  570.   /* Use verify since the sys_Continue command produces no return value */
  571.      
  572.   if (!DbgAttachDebugger(1))
  573.     return TCL_ERROR;
  574.  
  575.   if (argc==2) {
  576.     /* argv[1] is address to start execution at */
  577.     state.regs.PC = ParseAddress(argv[1]);
  578.     SetLabel(".state.pc",htoa(state.regs.PC));
  579.     
  580.     /*SetBreakpoint(port, 5, ParseAddress(argv[1]), 1);*/
  581.   }
  582.   
  583.   sys_Continue(port, &state.regs, 0);
  584.   
  585.   Say("Resuming execution\n");
  586.   
  587.   /* Assume the Pilot is no longer halted */
  588.   
  589.   debugger = 0;
  590.   console = 0;
  591.   stalestate = 1;
  592.   SetModeLabel();
  593.  
  594.   Tcl_VarEval(interp, "checkupin 25",NULL);
  595.   Tcl_ResetResult(interp);
  596.  
  597.   return TCL_OK;
  598. }
  599.  
  600. /* Till, restart execution */
  601. int proc_t(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  602. {
  603.   /* Use verify since the sys_Continue command produces no return value */
  604.      
  605.   if (!DbgAttachDebugger(1))
  606.     return TCL_ERROR;
  607.  
  608.   if (argc>=2) {
  609.     /* argv[1] is address to stop execution at */
  610.     SetBreakpoint(5, ParseAddress(argv[1]), 1);
  611.   }
  612.    
  613.   if (argc>=3) {
  614.     /* argv[2] is address to start execution at */
  615.     state.regs.PC = ParseAddress(argv[2]);
  616.     SetLabel(".state.pc",htoa(state.regs.PC));
  617.   }
  618.   
  619.   sys_Continue(port, &state.regs, 0);
  620.   
  621.   Say("Resuming execution\n");
  622.   
  623.   /* Assume the Pilot is no longer halted */
  624.   
  625.   debugger = 0;
  626.   console = 0;
  627.   stalestate = 1;
  628.   SetModeLabel();
  629.  
  630.   Tcl_VarEval(interp, "checkupin 25",NULL);
  631.   Tcl_ResetResult(interp);
  632.  
  633.   return TCL_OK;
  634. }
  635.  
  636. /* Attach to a Pilot that has already crashed into the debugger without notifying us */
  637. int proc_attach(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  638. {
  639.   DbgAttach(2); /* Two means explicit verify, as opposed to implicit */
  640.   
  641.   if (!debugger && !console) {
  642.      Say("Unable to attach to to Pilot. Is the Pilot connected and in debugging or console mode?\n");
  643.   }
  644.  
  645.   return TCL_OK;
  646. }
  647.  
  648. int proc_sendscreen(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  649. {
  650.   struct RPC_params p;
  651.  
  652.   PackRPC(&p, 0xA0F1, RPC_IntReply, RPC_Short(0), RPC_Short(0), RPC_Short(160), RPC_Short(160), RPC_End);
  653.   DbgRPC(&p, 0);
  654.   
  655.   return TCL_OK;
  656. }
  657.  
  658. int proc_coldboot(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  659. {
  660.   struct RPC_params p;
  661.  
  662.   PackRPC(&p, 0xA08B, RPC_NoReply, RPC_Long(0),RPC_Long(0),RPC_Long(0),RPC_Long(0), RPC_End);
  663.   DbgRPC(&p, 0);
  664.   
  665.   /* And sever attachment */
  666.   debugger = 0;
  667.   console = 0;
  668.   stalestate = 1;
  669.   SetModeLabel();
  670.  
  671.   Tcl_VarEval(interp, "checkupin 25",NULL);
  672.   Tcl_ResetResult(interp);
  673.  
  674.   return TCL_OK;
  675. }
  676.  
  677. int proc_warmboot(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  678. {
  679.   struct RPC_params p;
  680.  
  681.   PackRPC(&p, 0xA08C, RPC_NoReply, RPC_End);
  682.   DbgRPC(&p, 0);
  683.   
  684.   /* And sever attachment */
  685.   debugger = 0;
  686.   console = 0;
  687.   stalestate = 1;
  688.   SetModeLabel();
  689.   
  690.   Tcl_VarEval(interp, "checkupin 25",NULL);
  691.   Tcl_ResetResult(interp);
  692.  
  693.   return TCL_OK;
  694. }
  695.  
  696. int proc_battery(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  697. {
  698.             int err;
  699.             int warn, critical, maxTicks;
  700.             int v, kind, pluggedin;
  701.             char buffer[30];
  702.       struct RPC_params p;
  703.  
  704.   if (!DbgAttach(0))
  705.     return TCL_ERROR;
  706.  
  707.             warn = 0x1234;
  708.             critical = 0x2345;
  709.             maxTicks = 0x3456;
  710.             kind = 2;
  711.             pluggedin = 3;
  712.   
  713.         PackRPC(&p,0xA0B6, RPC_IntReply,
  714.             RPC_Byte(0), RPC_ShortPtr(&warn), RPC_ShortPtr(&critical),
  715.             RPC_ShortPtr(&maxTicks), RPC_BytePtr(&kind), RPC_BytePtr(&pluggedin), RPC_End);
  716.             
  717.      
  718.  
  719.       v =  DbgRPC(&p, &err);
  720.       
  721.      if (err)
  722.        return TCL_ERROR;
  723.       
  724. /*        printf("Volts = %f, crit = %f, warn = %f, ticks = %d, kind = %d, pluggedin= %d, err = %d\n",
  725.             (float)v/100, (float)critical/100, (float)warn/100,
  726.             maxTicks, kind, pluggedin, err);*/
  727.     
  728.     sprintf(buffer,"%.2f %s%s", (float)v/100, (kind == 0) ? "Alkaline" :
  729.                                               (kind == 1) ? "NiCd" :
  730.                                               (kind == 2) ? "Lithium" :
  731.                                               "",
  732.                                               pluggedin ? " Ext" : "" );
  733.     
  734.     Say(buffer);
  735.     
  736.     SetLabel(".state.battery",buffer);
  737.     
  738.     
  739. #ifdef TK
  740.     if (usetk) 
  741.         Tcl_VarEval(interp,".state.battery configure -fg ", (v <= critical) ? "red" :
  742.                                                             (v <= warn) ? "darkred" :
  743.                                                             "blue" , NULL);
  744. #endif    
  745.  
  746.     Say((v <= critical) ? " power critical!\n" : (v <= warn) ? " power low\n" : "\n");
  747.     
  748.     return TCL_OK;
  749. }
  750.  
  751. int proc_mirror(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  752. {
  753.   struct RPC_params p;
  754.   unsigned long addr;
  755.   int e1,e2;
  756.   int active;
  757.  
  758.   if (!DbgAttachConsole(0))
  759.     return TCL_ERROR;
  760.     
  761.   
  762.   /* Fetch scrGlobals ptr */
  763.  PackRPC(&p,0xA026, RPC_IntReply, RPC_LongPtr(&addr), RPC_Long(356), RPC_Long(4), RPC_End);
  764.   e1=DbgRPC(&p, &e2);
  765.   
  766.   /* Fetch current drawnotify setting */
  767.  PackRPC(&p,0xA026, RPC_IntReply, RPC_BytePtr(&active), RPC_Long(addr+18), RPC_Long(1), RPC_End);
  768.   e1=DbgRPC(&p, &e2);
  769.  
  770.   /*printf("addr=%d\nactive=%d\n", addr, active);*/
  771.  
  772.   /* Change setting */
  773.   if (argc<2)
  774.     active = !active;
  775.   else
  776.    if (Tcl_GetBoolean(interp, argv[1], &active)!=TCL_OK)
  777.      return TCL_ERROR;
  778.   
  779.   /* Put it back */
  780.  PackRPC(&p,0xA026, RPC_IntReply, RPC_Long(addr+18), RPC_BytePtr(&active), RPC_Long(1), RPC_End);
  781.   e1=DbgRPC(&p, &e2);
  782.  
  783.   if (Interactive) {
  784.     if (active)
  785.       Say("Mirroring is active.\n");
  786.     else
  787.       Say("Mirroring is inactive.\n");
  788.   }
  789.  
  790.   if (active) {
  791.     /* Try to prod Pilot into immediately giving us a screen update */
  792.     PackRPC(&p,0xA0F1, RPC_IntReply, RPC_Short(0), RPC_Short(0), RPC_Short(160), RPC_Short(160), RPC_End);
  793.     e1=DbgRPC(&p, &e2);
  794.   }
  795.   
  796.   return TCL_OK;  
  797. }
  798.  
  799. int proc_updatedisplay(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  800. {
  801.   struct RPC_params p;
  802.   int e1,e2;
  803.  
  804.   if (!DbgAttachConsole(0))
  805.     return TCL_ERROR;
  806.  
  807.   /* Try to prod Pilot into immediately giving us a screen update */
  808.   PackRPC(&p,0xA0F1, RPC_IntReply, RPC_Short(0), RPC_Short(0), RPC_Short(160), RPC_Short(160), RPC_End);
  809.   e1=DbgRPC(&p, &e2);
  810.   
  811.   return TCL_OK;  
  812. }
  813.  
  814. #define DB 0xFFFF0000
  815. #define LSSA 0xFA00  
  816.  
  817. int proc_getdisplay(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  818. {
  819. #ifndef TK
  820.   Say("getdisplay is not available due to pilot-debug being compiled without Tk support");
  821.   return TCL_ERROR;
  822.  
  823. #else  
  824.   char buffer[0xffff];
  825.   char buffer2[0xffff];
  826.   Tk_PhotoImageBlock block;
  827.   Tk_PhotoHandle handle;
  828.   struct RPC_params p;
  829.   unsigned long addr;
  830.   int e1,e2;
  831.   int l;
  832.  
  833.  
  834.   if (!usetk) {
  835.     Say("getdisplay is not usable when graphical display is disabled");
  836.     return TCL_ERROR;
  837.   }
  838.   
  839.   if (!DbgAttach(0))
  840.     return TCL_ERROR;
  841.     
  842.   
  843.   if (debugger) {
  844.       l = sys_ReadMemory(port, DB+LSSA, 4, buffer);
  845.       addr = get_long(buffer);
  846.       l = sys_ReadMemory(port, addr, 160*160/8, buffer);
  847.   } else {
  848.       PackRPC(&p,0xA026, RPC_IntReply, RPC_LongPtr(&addr), RPC_Long(DB+LSSA), RPC_Long(4), RPC_End);
  849.       e1=DbgRPC(&p, &e2);
  850.       for (l=0;l<160*160/8;l+=64) {
  851.           PackRPC(&p,0xA026, RPC_IntReply, RPC_Ptr(buffer+l, 128), RPC_Long(addr+l), RPC_Long(128), RPC_End);
  852.           e1=DbgRPC(&p, &e2);
  853.       }
  854.   }
  855.   
  856.   block.width = 160;
  857.   block.height = 160;
  858.   block.pitch = 160;
  859.   block.pixelSize = 1;
  860.   block.offset[0] = 0;
  861.   block.offset[1] = 0;
  862.   block.offset[2] = 0; 
  863.   
  864.   handle = Tk_FindPhoto("Case");
  865.  
  866.   for(l=0;l<160*160;l++) {
  867.       int p = l/8;
  868.       int b = 1<<(7-(l%8));
  869.       buffer2[l] = (buffer[p] & b) ? 0 : 0xff;
  870.   }
  871.   block.pixelPtr = buffer2;
  872.   Tk_PhotoPutBlock(handle, &block, 32, 33, 160, 160);
  873.   
  874.   return TCL_OK;  
  875. #endif
  876. }
  877.  
  878. int proc_transmit(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  879. {
  880.   if (argc < 2)
  881.     return TCL_OK;
  882.   
  883.   if (!DbgAttachConsole(0))
  884.     return TCL_ERROR;
  885.     
  886.   buffer[0] = 1;
  887.   buffer[1] = 1;
  888.   buffer[2] = 0;
  889.   buffer[3] = 0;
  890.   buffer[4] = 0x7f;
  891.   buffer[5] = 0;
  892.   strcpy(buffer+6, argv[1]);
  893.   strcat(buffer+6, "\n");
  894.   
  895.   pi_write(port, buffer, 6+strlen(argv[1])+2);
  896.   
  897.   return TCL_OK;  
  898. }
  899.  
  900. int proc_pushbutton(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  901. {
  902.   struct RPC_params p;
  903.   unsigned int key=0, scan=0, mod=0;
  904.   
  905.   if (!DbgAttachConsole(0))
  906.     return TCL_ERROR;
  907.   
  908.   sys_RPCerror = 0;
  909.   switch(atoi(argv[1])) {
  910.     case 0: /* Backlight */
  911.         key = 0x0113;
  912.         mod = 0x08;
  913.         break;
  914.         
  915.     case 1: /* Power */
  916.         key = 0x0208;
  917.         mod = 0x08;
  918.         break;
  919.  
  920.     case 2: /* Datebook */
  921.         key = 0x0204;
  922.         mod = 0x08;
  923.         break;
  924.     case 3: /* Address */
  925.         key = 0x0205;
  926.         mod = 0x08;
  927.         break;
  928.     case 6: /* ToDo */
  929.         key = 0x0206;
  930.         mod = 0x08;
  931.         break;
  932.     case 7: /* Memo */
  933.         key = 0x0207;
  934.         mod = 0x08;
  935.         break;
  936.  
  937.     case 4: /* Page Up */
  938.         key = 0x000b;
  939.         mod = 0;
  940.         break;
  941.     case 5: /* Page Down */
  942.         key = 0x000c;
  943.         mod = 0;
  944.         break;
  945.     default:
  946.         return Error("Button number out of range (1-7)");
  947.   }
  948.  
  949.   PackRPC(&p, 0xA12D, RPC_IntReply, RPC_Short(key),RPC_Short(scan),RPC_Short(mod), RPC_End);
  950.   
  951.   DbgRPC(&p, 0);
  952.   
  953.   return TCL_OK;
  954. }
  955.  
  956. /* Tcl procedure to simulate a pen tap -- primarily used by Remote UI bindings */
  957. int proc_pen(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  958. {
  959.   int x = atoi(argv[1])-32, y = atoi(argv[2])-33, pen = atoi(argv[3]);
  960.   
  961.   /* Transmit Pen event to Pilot */
  962.   
  963.  /*printf("Pen %d, %d, %d\n", x, y, pen);*/
  964.   
  965.  if (!DbgAttachConsole(0))
  966.     return TCL_ERROR;
  967.   
  968.   sys_RemoteEvent(port, pen, x, y, 0, 0,0,0);
  969.   
  970.   return TCL_OK;
  971. }
  972.  
  973. /* Tcl procedure to simulate a key press -- primarily used by Remote UI bindings */
  974. int proc_key(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  975. {
  976.   /*struct RPC_params p;*/
  977.   int key = argv[1][0];
  978.   /* Change \r to \n */
  979.   if (key == 13) key = 10;
  980.   
  981.   /* Transmit ASCII key to Pilot */
  982.  
  983.   /*printf("Key %d\n", key);*/
  984.   
  985.   /*PackRPC(&p, 0xA12D, RPC_IntReply, RPC_Short(key),RPC_Short(0),RPC_Short(0x0), RPC_End);
  986.  
  987.   if (key != 0)
  988.     DbgRPC(&p, 0);*/
  989.  
  990.  if (!DbgAttachConsole(0))
  991.     return TCL_ERROR;
  992.  
  993.  sys_RemoteEvent(port, 0, 0, 0, 1, 0, key, 0);
  994.   
  995. /*  int sd, int penDown, int x, int y, int keypressed,
  996.                          int keymod, int keyasc, int keycode)*/
  997.                          
  998.   
  999.   return TCL_OK;
  1000. }
  1001.  
  1002. int proc_port(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  1003. {
  1004.   static struct pi_sockaddr laddr;
  1005.   static Tcl_Channel channel;
  1006.   int fd;
  1007.   
  1008.   if (argc<2) {
  1009.       if(port)
  1010.         Tcl_SetResult(interp, laddr.pi_device, TCL_STATIC);
  1011.     return TCL_OK;
  1012.   }
  1013.   
  1014.   if (port) {
  1015.     Tcl_DeleteChannelHandler(channel, Read_Pilot, (ClientData)port);
  1016.     Tcl_UnregisterChannel(interp, channel);
  1017.     pi_close(port);
  1018.     port = 0;
  1019.   }
  1020.   
  1021.   if (strcmp(argv[1],"close")==0) {
  1022.       return TCL_OK;
  1023.   }
  1024.   
  1025.   port = pi_socket(PI_AF_SLP, PI_SOCK_RAW, PI_PF_SLP);
  1026.   
  1027.   laddr.pi_family = PI_AF_SLP;
  1028.   strcpy(laddr.pi_device,argv[1]);
  1029.   
  1030.   if (pi_bind(port, (struct sockaddr*)&laddr, sizeof(laddr))==-1) {
  1031.     Say("Unable to open port '");
  1032.     Say(argv[1]);
  1033.     Say("': ");
  1034.     Say(Tcl_ErrnoMsg(errno));
  1035.     Say("\n");
  1036.     port = 0;
  1037.     return TCL_ERROR;
  1038.   }
  1039.   
  1040.   fd = port;
  1041.  
  1042. #if (TCL_MAJOR_VERSION<8) || (TCL_RELEASE_LEVEL<1)
  1043.   channel = Tcl_MakeFileChannel((ClientData)fd, 0, TCL_READABLE);
  1044. #else
  1045.   channel = Tcl_MakeFileChannel((ClientData)fd, TCL_READABLE);
  1046. #endif
  1047.   Tcl_RegisterChannel(interp, channel); /* And register it to TCL */
  1048.   Tcl_CreateChannelHandler(channel, TCL_READABLE, Read_Pilot, (ClientData)port);
  1049.   
  1050.   Tcl_SetResult(interp, laddr.pi_device, TCL_STATIC);
  1051.   return TCL_OK;
  1052. }
  1053.  
  1054. int proc_inittkdbg(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  1055. {
  1056. #ifndef TK
  1057.   Say("This executable does not contain Tk support!\n");
  1058.   return TCL_ERROR;
  1059. #else
  1060.   static int created = 0;
  1061.   if (created) {
  1062.     Say("Graphical debugger already initialized.\n");
  1063.     return TCL_OK;
  1064.   }
  1065.  
  1066.   Tcl_VarEval(interp,"\
  1067.  
  1068. ###  /*** Generate remote UI window ***/
  1069.  
  1070. set tkdbg 1
  1071.  
  1072. toplevel .remote
  1073. wm title .remote {Pilot Remote UI}
  1074.  
  1075. catch {
  1076.     if {[file exists {pix/case.gif}]} {
  1077.         set dir {pix}
  1078.     } elseif {[file exists {",LIBDIR,"/pix/case.gif}]} {
  1079.         set dir {",LIBDIR,"/pix}
  1080.     } else {
  1081.         error {No pix}
  1082.     }
  1083.     image create photo Case -format gif -file \"$dir/case.gif\"
  1084.     image create photo B1 -format gif -file \"$dir/b1.gif\"
  1085.     image create photo B2 -format gif -file \"$dir/b2.gif\"
  1086.     image create photo B3 -format gif -file \"$dir/b3.gif\"
  1087.     image create photo B4 -format gif -file \"$dir/b4.gif\"
  1088.     image create photo B5 -format gif -file \"$dir/b5.gif\"
  1089.     image create photo B6 -format gif -file \"$dir/b6.gif\"
  1090.     image create photo B7 -format gif -file \"$dir/b7.gif\"
  1091. }
  1092.  
  1093. canvas .remote.c -width 221 -height 337
  1094.  
  1095. .remote.c create rectangle 27 29 196 260 -outline {red} -tag screen -fill {blue}
  1096. .remote.c create rectangle 0 280 18 306 -outline {red} -tag button1 -fill {blue}
  1097. .remote.c create oval 23 276 52 307 -outline {red} -tag button2 -fill {blue}
  1098. .remote.c create oval 63 276 92 307 -outline {red} -tag button3 -fill {blue}
  1099. .remote.c create rectangle 97 277 127 294 -outline {red} -tag button4 -fill {blue}
  1100. .remote.c create rectangle 97 300 127 317 -outline {red} -tag button5 -fill {blue}
  1101. .remote.c create oval 133 276 162 307 -outline {red} -tag button6 -fill {blue}
  1102. .remote.c create oval 171 276 200 307 -outline {red} -tag button7 -fill {blue}
  1103.  
  1104. .remote.c create rectangle 33 32 187 253 -outline black -tag screen
  1105. .remote.c create rectangle 33 200 61 225 -outline black -tag screen
  1106. .remote.c create rectangle 33 225 61 253 -outline black -tag screen
  1107. .remote.c create rectangle 160 200 187 225 -outline black -tag screen
  1108. .remote.c create rectangle 160 225 187 253 -outline black -tag screen
  1109. .remote.c create rectangle 62 200 159 253 -outline black -tag screen
  1110.  
  1111. set buttons(1) 0
  1112.  
  1113. proc holdbutton {button} {
  1114.     global buttons
  1115.     if {$button==1} {
  1116.         set buttons($button) [after 1000 \"continuebutton $button\"]
  1117.     } else {
  1118.         pushbutton $button
  1119.         set buttons($button) [after 250 \"holdbutton $button\"]
  1120.     }
  1121. }
  1122.  
  1123. proc continuebutton {button} {
  1124.     global buttons
  1125.     if {$button==1} {
  1126.         pushbutton 0
  1127.     }
  1128.     set buttons($button) \"\"
  1129. }
  1130.  
  1131. proc releasebutton {button} {
  1132.     global buttons
  1133.     if {$buttons($button)!=\"\"} {
  1134.         if {$button==1} {
  1135.             pushbutton 1
  1136.         }
  1137.         after cancel $buttons($button)
  1138.         set buttons($button) \"\"
  1139.     }
  1140. }
  1141.  
  1142. .remote.c bind button1 <ButtonPress-1> {.remote.c itemconfigure button1 -fill green; update; holdbutton 1}
  1143. .remote.c bind button1 <ButtonRelease-1> {.remote.c itemconfigure button1 -fill blue; releasebutton 1}
  1144.  
  1145. .remote.c bind button2 <ButtonPress-1> {.remote.c itemconfigure button2 -fill green; update; holdbutton 2}
  1146. .remote.c bind button2 <ButtonRelease-1> {.remote.c itemconfigure button2 -fill blue; releasebutton 2}
  1147.  
  1148. .remote.c bind button3 <ButtonPress-1> {.remote.c itemconfigure button3 -fill green; update; holdbutton 3}
  1149. .remote.c bind button3 <ButtonRelease-1> {.remote.c itemconfigure button3 -fill blue; releasebutton 3}
  1150.  
  1151. .remote.c bind button4 <ButtonPress-1> {.remote.c itemconfigure button4 -fill green; update; holdbutton 4}
  1152. .remote.c bind button4 <ButtonRelease-1> {.remote.c itemconfigure button4 -fill blue; releasebutton 4}
  1153.  
  1154. .remote.c bind button5 <ButtonPress-1> {.remote.c itemconfigure button5 -fill green; update; holdbutton 5}
  1155. .remote.c bind button5 <ButtonRelease-1> {.remote.c itemconfigure button5 -fill blue; releasebutton 5}
  1156.  
  1157. .remote.c bind button6 <ButtonPress-1> {.remote.c itemconfigure button6 -fill green; update; holdbutton 6}
  1158. .remote.c bind button6 <ButtonRelease-1> {.remote.c itemconfigure button6 -fill blue; releasebutton 6}
  1159.  
  1160. .remote.c bind button7 <ButtonPress-1> {.remote.c itemconfigure button7 -fill green; update; holdbutton 7}
  1161. .remote.c bind button7 <ButtonRelease-1> {.remote.c itemconfigure button7 -fill blue; releasebutton 7}
  1162.  
  1163. catch {
  1164.     .remote.c create image 0 282 -image B1 -anchor nw -tag downbutton1
  1165.     .remote.c create image 22 274 -image B2 -anchor nw -tag downbutton2
  1166.     .remote.c create image 60 275 -image B3 -anchor nw -tag downbutton3
  1167.     .remote.c create image 93 278 -image B4 -anchor nw -tag downbutton4
  1168.     .remote.c create image 95 298 -image B5 -anchor nw -tag downbutton5
  1169.     .remote.c create image 131 275 -image B6 -anchor nw -tag downbutton6
  1170.     .remote.c create image 169 274 -image B7 -anchor nw -tag downbutton7
  1171.  
  1172.     .remote.c create image 0 0 -image Case -anchor nw
  1173.  
  1174.     .remote.c bind button1 <ButtonPress-1> {.remote.c raise downbutton1; update; holdbutton 1}
  1175.     .remote.c bind button1 <ButtonRelease-1> {.remote.c lower downbutton1; releasebutton 1}
  1176.  
  1177.     .remote.c bind button2 <ButtonPress-1> {.remote.c raise downbutton2; update; holdbutton 2}
  1178.     .remote.c bind button2 <ButtonRelease-1> {.remote.c lower downbutton2; releasebutton 2}
  1179.  
  1180.     .remote.c bind button3 <ButtonPress-1> {.remote.c raise downbutton3; update; holdbutton 3}
  1181.     .remote.c bind button3 <ButtonRelease-1> {.remote.c lower downbutton3; releasebutton 3}
  1182.  
  1183.     .remote.c bind button4 <ButtonPress-1> {.remote.c raise downbutton4; update; holdbutton 4}
  1184.     .remote.c bind button4 <ButtonRelease-1> {.remote.c lower downbutton4; releasebutton 4}
  1185.  
  1186.     .remote.c bind button5 <ButtonPress-1> {.remote.c raise downbutton5; update; holdbutton 5}
  1187.     .remote.c bind button5 <ButtonRelease-1> {.remote.c lower downbutton5; releasebutton 5}
  1188.  
  1189.     .remote.c bind button6 <ButtonPress-1> {.remote.c raise downbutton6; update; holdbutton 6}
  1190.     .remote.c bind button6 <ButtonRelease-1> {.remote.c lower downbutton6; releasebutton 6}
  1191.  
  1192.     .remote.c bind button7 <ButtonPress-1> {.remote.c raise downbutton7; update; holdbutton 7}
  1193.     .remote.c bind button7 <ButtonRelease-1> {.remote.c lower downbutton7; releasebutton 7}
  1194.     
  1195.     
  1196.     .remote.c itemconfigure button1 -outline {} -fill {}
  1197.     .remote.c raise button1
  1198.     .remote.c itemconfigure button2 -outline {} -fill {}
  1199.     .remote.c raise button2
  1200.     .remote.c itemconfigure button3 -outline {} -fill {}
  1201.     .remote.c raise button3
  1202.     .remote.c itemconfigure button4 -outline {} -fill {}
  1203.     .remote.c raise button4
  1204.     .remote.c itemconfigure button5 -outline {} -fill {}
  1205.     .remote.c raise button5
  1206.     .remote.c itemconfigure button6 -outline {} -fill {}
  1207.     .remote.c raise button6
  1208.     .remote.c itemconfigure button7 -outline {} -fill {}
  1209.     .remote.c raise button7
  1210.     .remote.c itemconfigure screen -outline {} -fill {}
  1211.     .remote.c raise screen
  1212. }
  1213.  
  1214. pack .remote.c -side top
  1215.  
  1216. .remote.c bind screen <ButtonPress-1> {pen %x %y 1}
  1217. .remote.c bind screen <B1-Motion> {pen %x %y 1}
  1218. .remote.c bind screen <ButtonRelease-1> {pen %x %y 0}
  1219.  
  1220. global KeyQueue
  1221. global KeyQueueId
  1222. global KeyQueueDelay
  1223. set KeyQueue {}
  1224. set KeyQueueId {}
  1225. set KeyQueueDelay 50
  1226.  
  1227. proc readyqueue {} {
  1228.     global KeyQueueId
  1229.     global KeyQueueDelay
  1230.     if {$KeyQueueId == {}} {
  1231.     after $KeyQueueDelay { set KeyQueueId [ after idle {sendqueue} ] }
  1232.     }
  1233. }
  1234.  
  1235. proc queuekey {c} {
  1236.     global KeyQueue
  1237.     append KeyQueue $c
  1238.     readyqueue
  1239. }
  1240.  
  1241. proc sendqueue {} {
  1242.     global KeyQueue
  1243.     global KeyQueueId
  1244.     if {[string length $KeyQueue] > 0} {
  1245.     key [string index $KeyQueue 0]
  1246.     set KeyQueue [string range $KeyQueue 1 end]
  1247.     }
  1248.     set KeyQueueId {}
  1249.     if {[string length $KeyQueue] > 0} { readyqueue }
  1250. }
  1251.  
  1252. bind .remote <KeyPress> {queuekey %A}
  1253.  
  1254. ## Handle pasting
  1255. proc do_paste { } {
  1256.     if [catch {selection get} sel] {
  1257.     if [catch {selection get -selection CLIPBOARD} sel] {
  1258.         return
  1259.     }
  1260.     }
  1261.     queuekey $sel
  1262. }
  1263. bind .remote <ButtonPress-2> {do_paste}
  1264.  
  1265. #####  /*** Generate remote console window ***/
  1266.  
  1267. toplevel .console
  1268. wm title .console \"Pilot Remote Console\"
  1269. scrollbar .console.y -orient vertical -command {.console.t yview}
  1270. text .console.t -yscrollcommand {.console.y set}
  1271. pack .console.t -fill both -expand yes -side left
  1272. pack .console.y -fill y -side right
  1273. focus .console.t
  1274.  
  1275. ####  /*** Generate pilot state window ***/
  1276.  
  1277. toplevel .state
  1278. wm title .state {Pilot State}
  1279. label .state.l1 -text {Active mode:}
  1280. label .state.l1x -text {Battery:}
  1281. label .state.l2 -text {Exception:}
  1282. label .state.l25 -text {Reset:}
  1283. label .state.l3 -text {Function:}
  1284. label .state.l4 -text {F-start:}
  1285. label .state.l5 -text {F-end:}
  1286. label .state.l6 -text {D0:}
  1287. label .state.l7 -text {A0:}
  1288. label .state.l8 -text {D1:}
  1289. label .state.l9 -text {A1:}
  1290. label .state.l10 -text {D2:}
  1291. label .state.l11 -text {A2:}
  1292. label .state.l12 -text {D3:}
  1293. label .state.l13 -text {A3:}
  1294. label .state.l14 -text {D4:}
  1295. label .state.l15 -text {A4:}
  1296. label .state.l16 -text {D5:}
  1297. label .state.l17 -text {A5:}
  1298. label .state.l18 -text {D6:}
  1299. label .state.l19 -text {A6:}
  1300. label .state.l20 -text {D7:}
  1301.  
  1302. label .state.l21 -text {PC:}
  1303. label .state.l22 -text {SR:}
  1304. label .state.l23 -text {USP:}
  1305. label .state.l24 -text {SSP:}
  1306.  
  1307. label .state.halted -text {None}
  1308. label .state.battery -text {Unknown}
  1309. label .state.exception -text {0}
  1310. label .state.reset -text {No}
  1311. label .state.funcname -text {}
  1312. label .state.funcstart -text {00000000}
  1313. label .state.funcend -text {00000000}
  1314. label .state.d0 -text {00000000}
  1315. label .state.a0 -text {00000000}
  1316. label .state.d1 -text {00000000}
  1317. label .state.a1 -text {00000000}
  1318. label .state.d2 -text {00000000}
  1319. label .state.a2 -text {00000000}
  1320. label .state.d3 -text {00000000}
  1321. label .state.a3 -text {00000000}
  1322. label .state.d4 -text {00000000}
  1323. label .state.a4 -text {00000000}
  1324. label .state.d5 -text {00000000}
  1325. label .state.a5 -text {00000000}
  1326. label .state.d6 -text {00000000}
  1327. label .state.a6 -text {00000000}
  1328. label .state.d7 -text {00000000}
  1329. label .state.pc -text {00000000}
  1330. label .state.sr -text {0000}
  1331. label .state.usp -text {00000000}
  1332. label .state.ssp -text {00000000}
  1333.  
  1334. grid .state.l1 -column 0 -row 0 -sticky e -columnspan 2
  1335. grid .state.halted -column 2 -row 0 -sticky w -columnspan 2
  1336.  
  1337. grid .state.l1x -column 0 -row 1 -sticky e -columnspan 2
  1338. grid .state.battery -column 2 -row 1 -sticky w -columnspan 2
  1339.  
  1340. grid .state.l2 -column 0 -row 2 -sticky e -columnspan 2
  1341. grid .state.exception -column 2 -row 2 -sticky w -columnspan 2
  1342.  
  1343. grid .state.l25 -column 0 -row 3 -sticky e -columnspan 2
  1344. grid .state.reset -column 2 -row 3 -sticky w -columnspan 2
  1345.  
  1346. grid .state.l3 -column 0 -row 4 -sticky e -columnspan 2 
  1347. grid .state.funcname -column 2 -row 4 -sticky w -columnspan 2
  1348.  
  1349. grid .state.l4 -column 0 -row 5 -sticky e -columnspan 2 
  1350. grid .state.funcstart -column 2 -row 5 -sticky w -columnspan 2
  1351.  
  1352. grid .state.l5 -column 0 -row 6 -sticky e -columnspan 2 
  1353. grid .state.funcend -column 2 -row 6 -sticky w -columnspan 2
  1354.  
  1355. frame .state.rule1 -relief raised -bd 2 -height 4
  1356. grid .state.rule1 -column 0 -row 7 -columnspan 4 -sticky ew
  1357.  
  1358. grid .state.l6 -column 0 -row 8 -sticky e 
  1359. grid .state.d0 -column 1 -row 8 -sticky w
  1360. grid .state.l7 -column 2 -row 8 -sticky e 
  1361. grid .state.a0 -column 3 -row 8 -sticky w
  1362.  
  1363. grid .state.l8 -column 0 -row 9 -sticky e 
  1364. grid .state.d1 -column 1 -row 9 -sticky w
  1365. grid .state.l9 -column 2 -row 9 -sticky e 
  1366. grid .state.a1 -column 3 -row 9 -sticky w
  1367.  
  1368. grid .state.l10 -column 0 -row 10 -sticky e 
  1369. grid .state.d2 -column 1 -row 10 -sticky w
  1370. grid .state.l11 -column 2 -row 10 -sticky e 
  1371. grid .state.a2 -column 3 -row 10 -sticky w
  1372.  
  1373. grid .state.l12 -column 0 -row 11 -sticky e 
  1374. grid .state.d3 -column 1 -row 11 -sticky w
  1375. grid .state.l13 -column 2 -row 11 -sticky e 
  1376. grid .state.a3 -column 3 -row 11 -sticky w
  1377.  
  1378. grid .state.l14 -column 0 -row 12 -sticky e 
  1379. grid .state.d4 -column 1 -row 12 -sticky w
  1380. grid .state.l15 -column 2 -row 12 -sticky e 
  1381. grid .state.a4 -column 3 -row 12 -sticky w
  1382.  
  1383. grid .state.l16 -column 0 -row 13 -sticky e 
  1384. grid .state.d5 -column 1 -row 13 -sticky w
  1385. grid .state.l17 -column 2 -row 13 -sticky e 
  1386. grid .state.a5 -column 3 -row 13 -sticky w
  1387.  
  1388. grid .state.l18 -column 0 -row 14 -sticky e 
  1389. grid .state.d6 -column 1 -row 14 -sticky w
  1390. grid .state.l19 -column 2 -row 14 -sticky e 
  1391. grid .state.a6 -column 3 -row 14 -sticky w
  1392.  
  1393. grid .state.l20 -column 0 -row 15 -sticky e 
  1394. grid .state.d7 -column 1 -row 15 -sticky w
  1395.  
  1396. grid .state.l21 -column 0 -row 16 -sticky e 
  1397. grid .state.pc -column 1 -row 16 -sticky w
  1398. grid .state.l22 -column 2 -row 16 -sticky e 
  1399. grid .state.sr -column 3 -row 16 -sticky w
  1400.  
  1401. grid .state.l23 -column 0 -row 17 -sticky e 
  1402. grid .state.usp -column 1 -row 17 -sticky w
  1403. grid .state.l24 -column 2 -row 17 -sticky e 
  1404. grid .state.ssp -column 3 -row 17 -sticky w
  1405.  
  1406. label .state.bl2 -text {B1:}
  1407. label .state.bl4 -text {B2:}
  1408. label .state.bl6 -text {B3:}
  1409. label .state.bl8 -text {B4:}
  1410. label .state.bl10 -text {B5:}
  1411. label .state.bl12 -text {B6:}
  1412.  
  1413. label .state.b1 -text {00000000}
  1414. label .state.b1a -text {Off}
  1415. label .state.b2 -text {00000000}
  1416. label .state.b2a -text {Off}
  1417. label .state.b3 -text {00000000}
  1418. label .state.b3a -text {Off}
  1419. label .state.b4 -text {00000000}
  1420. label .state.b4a  -text {Off}
  1421. label .state.b5 -text {00000000}
  1422. label .state.b5a -text {Off}
  1423. label .state.b6 -text {00000000}
  1424. label .state.b6a -text {Off}
  1425.  
  1426. frame .state.rule2 -relief raised -bd 2 -height 4
  1427. grid .state.rule2 -column 0 -row 18 -columnspan 4 -sticky ew
  1428.  
  1429. grid .state.bl2 -column 0 -row 19 -sticky e
  1430. grid .state.b1 -column 1 -row 19 -sticky w
  1431. grid .state.b1a -column 2 -row 19 -sticky w 
  1432.  
  1433. grid .state.bl4 -column 0 -row 20 -sticky e
  1434. grid .state.b2 -column 1 -row 20 -sticky w
  1435. grid .state.b2a -column 2 -row 20 -sticky w 
  1436.  
  1437. grid .state.bl6 -column 0 -row 21 -sticky e
  1438. grid .state.b3 -column 1 -row 21 -sticky w
  1439. grid .state.b3a -column 2 -row 21 -sticky w 
  1440.  
  1441. grid .state.bl8 -column 0 -row 22 -sticky e
  1442. grid .state.b4 -column 1 -row 22 -sticky w
  1443. grid .state.b4a -column 2 -row 22 -sticky w 
  1444.  
  1445. grid .state.bl10 -column 0 -row 23 -sticky e
  1446. grid .state.b5 -column 1 -row 23 -sticky w
  1447. grid .state.b5a -column 2 -row 23 -sticky w 
  1448.  
  1449. grid .state.bl12 -column 0 -row 24 -sticky e
  1450. grid .state.b6 -column 1 -row 24 -sticky w
  1451. grid .state.b6a -column 2 -row 24 -sticky w 
  1452.  
  1453. ###  /*** Generate debugger console window ***/
  1454.  
  1455. wm title . \"Pilot Debugger Console\"
  1456. catch {
  1457.     wm iconbitmap . {@pix/case.xbm}
  1458.     wm iconbitmap .remote {@pix/case.xbm}
  1459.     wm iconbitmap .console {@pix/case.xbm}
  1460.     wm iconbitmap .state {@pix/case.xbm}
  1461.     #wm iconmask . {@pix/casemask.xbm}
  1462. }
  1463.  
  1464. frame .m -relief raised
  1465. frame .f
  1466. scrollbar .f.y -orient vertical -command {.f.t yview}
  1467. text .f.t -yscrollcommand {.f.y set} -wrap word
  1468. pack .f.t -fill both -expand yes -side left
  1469. pack .f.y -fill y -side right
  1470. pack [menubutton .m.file -text {File} -menu .m.file.m] -side left
  1471. #pack [menubutton .m.edit -text {Edit} -menu .m.edit.m] -side left
  1472. pack [menubutton .m.windows -text {Windows} -menu .m.windows.m] -side left
  1473. #pack [menubutton .m.help -text {Help} -menu .m.help.m] -side right
  1474.  
  1475. menu .m.file.m
  1476. menu .m.windows.m
  1477. #menu .m.edit.m
  1478. #menu .m.help.m
  1479.  
  1480. #wm iconify .remote
  1481. #wm iconify .console
  1482. #wm iconify .state
  1483.  
  1484.  
  1485. proc ShowWindow {name1 name2 op} {
  1486.   global show
  1487.   if {$show($name2)} {
  1488.     if {[wm state $name2] != \"normal\"} {
  1489.       wm deiconify $name2
  1490.     }
  1491.   } else {
  1492.     if {[wm state $name2] == \"normal\"} {
  1493.       wm withdraw $name2
  1494.     }
  1495.   }
  1496. }
  1497.  
  1498.  
  1499. trace variable show w {ShowWindow}
  1500.  
  1501. bind .remote <Unmap> { set show(.remote) 0 }
  1502. bind .console <Unmap> { set show(.console) 0 }
  1503. bind .state <Unmap> { set show(.state) 0 }
  1504.  
  1505. bind .remote <Map> { set show(.remote) 1 }
  1506. bind .console <Map> { set show(.console) 1 }
  1507. bind .state <Map> { set show(.state) 1 }
  1508.  
  1509. wm protocol .remote WM_DELETE_WINDOW { set show(.remote) 0 }
  1510. wm protocol .console WM_DELETE_WINDOW { set show(.console) 0 }
  1511. wm protocol .state WM_DELETE_WINDOW { set show(.state) 0 }
  1512.  
  1513. set show(.remote) 0
  1514. set show(.console) 0
  1515. set show(.state) 0
  1516.  
  1517.  
  1518. .m.file.m add command -label {Exit} -command {exit}
  1519.  
  1520. .m.windows.m add checkbutton -label {Remote UI} -var show(.remote)
  1521. .m.windows.m add checkbutton -label {Remote Console} -var show(.console)
  1522. .m.windows.m add checkbutton -label {Remote State} -var show(.state)
  1523.  
  1524. pack .m -side top -fill x
  1525. pack .f -side top -fill both -expand yes
  1526. focus .f.t
  1527.  
  1528. ###  /*** Configure console bindings ***/
  1529.  
  1530. bind .console.t <Shift-KeyPress-Return> {tkTextInsert .console.t \"\\n\" ; break}
  1531. bind .f.t <Shift-KeyPress-Return> {tkTextInsert .f.t \"\\n\" ; break}
  1532.  
  1533. bind .console.t <Control-KeyPress-Return> {tkTextInsert .console.t \"\\n\" ; break}
  1534. bind .f.t <Control-KeyPress-Return> {tkTextInsert .f.t \"\\n\" ; break}
  1535.  
  1536. bind .console.t <KeyPress-Return> {Console [.console.t get {insert linestart} {insert lineend}] ; break}
  1537. bind .f.t <KeyPress-Return> {
  1538.     set line [.f.t get {insert linestart} {insert lineend}]
  1539.     set f [string first \">\" $line]
  1540.     incr f
  1541.     set line [string range $line $f end]
  1542.     .f.t mark set insert {insert lineend}
  1543.     .f.t insert insert \\n
  1544.     Debugger $line
  1545.     if {[.f.t compare insert != {insert linestart}]} {
  1546.         .f.t insert insert \"\\n\"
  1547.     }
  1548.     .f.t insert insert \"pilot-debug> \"
  1549.     .f.t see insert
  1550.     break
  1551. }
  1552.  
  1553. proc Console {cmd} {
  1554.     .console.t mark set insert {insert lineend}
  1555.     tkTextInsert .console.t \\n
  1556.     transmit $cmd
  1557. }
  1558.  
  1559. proc Debugger {cmd} {
  1560.     #.f.t mark set insert {insert lineend}
  1561.     #tkTextInsert .f.t \\n
  1562.     if {[string length [string trim $cmd]]!=0} {
  1563.         set code [catch {eval $cmd} message]
  1564.         if {[string length $message]} {
  1565.             set message [string trimright $message]
  1566.             Say \"$message\\n\"
  1567.             #if {[.f.t compare insert != {insert linestart}]} {
  1568.             #    Say \"\\\n\"
  1569.             #}
  1570.         }
  1571.     }
  1572. }
  1573.  
  1574. proc Say {text} {
  1575.     global Interactive
  1576.     if {$Interactive} {
  1577.       .f.t insert insert \"$text\"
  1578.       .f.t see insert
  1579.     } else {
  1580.       upvar result result
  1581.       set result \"$result$text\"
  1582.     }
  1583. }
  1584.  
  1585. ", NULL);
  1586.   puts(interp->result);
  1587.   
  1588.   created = 1;
  1589.   usetk = 1;
  1590.  
  1591.   return TCL_OK;
  1592. #endif
  1593. }
  1594.  
  1595. int proc_help(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  1596. {
  1597.   Say("\
  1598. --- Help ---\n\
  1599. g [<addr>]\tGo: Resume execution (if address is supplied, will start at that point)\n\
  1600. t <addr1> [<addr2>}\tTill: Resume execution until addr1 (if addr2 is supplied, will start at that point)\n\
  1601. coldboot\n\
  1602. warmboot\n\
  1603. pushbutton <button number>\tSimulate button push\n\
  1604. mirror [bool]\tContinually view the Pilot's screen in the Remote UI window (if bool supplied, can turn on or off mirroring, otherwise toggles)\n\
  1605. getdisplay\tShow the Pilot's display in the Remote UI window\n\
  1606. updatedisplay\tForce a mirror refresh\n\
  1607. ");
  1608.   return TCL_OK;
  1609. }
  1610.  
  1611. struct { char * name; Tcl_CmdProc * proc; } cmds[] = {
  1612.     { "coldboot",    proc_coldboot },
  1613.     { "warmboot",    proc_warmboot },
  1614.     { "sendscreen",    proc_sendscreen },
  1615.     { "pushbutton",    proc_pushbutton },
  1616.     { "pen",    proc_pen },
  1617.     { "key",    proc_key },
  1618.     { "g",        proc_g },
  1619.     { "t",        proc_t },
  1620.     { "attach",    proc_attach },
  1621.     { "transmit",    proc_transmit },
  1622.     { "getdisplay",    proc_getdisplay },
  1623.     { "updatedisplay",    proc_updatedisplay },
  1624.     { "mirror",     proc_mirror },
  1625.     { "battery",    proc_battery },
  1626.     { "port",    proc_port },
  1627.     { "help",    proc_help },
  1628.     { "inittkdbg",  proc_inittkdbg },
  1629.     { 0, 0}
  1630. };
  1631.  
  1632. int
  1633. Tcl_AppInit(myinterp)
  1634.     Tcl_Interp *myinterp;        /* Interpreter for application. */
  1635. {
  1636.     int i;
  1637.     
  1638.     interp=myinterp;
  1639.   
  1640.     if (Tcl_Init(interp) == TCL_ERROR) {
  1641.     return TCL_ERROR;
  1642.     }
  1643. #ifdef TK
  1644.     if (usetk) {    
  1645.         if (Tk_Init(interp) == TCL_ERROR) {
  1646.           return TCL_ERROR;
  1647.         }
  1648.         Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL);
  1649.     }
  1650. #endif
  1651.  
  1652.   /*** Load custom Tcl procedures ***/
  1653.  
  1654.  
  1655.   for (i=0;cmds[i].name;i++) {
  1656.     Tcl_CreateCommand(interp, cmds[i].name, cmds[i].proc, 0, NULL);
  1657.   }
  1658.   
  1659.   Tcl_VarEval(interp,"\
  1660. proc Say {text} {
  1661.     global Interactive
  1662.     if {$Interactive} {
  1663.       puts \"$text\"
  1664.     } else {
  1665.       upvar result result
  1666.       set result \"$result$text\"
  1667.     }
  1668. }
  1669.  
  1670. proc interactive {args} {
  1671.     global Interactive
  1672.     global errorInfo
  1673.     set hold $Interactive
  1674.     set Interactive 1
  1675.     set code [catch $args message]
  1676.     set Interactive $hold
  1677.     error $message $errorInfo $code
  1678. }
  1679.  
  1680. proc noninteractive {args} {
  1681.     global Interactive
  1682.     global errorInfo
  1683.     set hold $Interactive
  1684.     set Interactive 0
  1685.     set code [catch $args message]
  1686.     set Interactive $hold
  1687.     error $message $errorInfo $code
  1688. }
  1689.  
  1690. set Interactive 1
  1691.  
  1692.  
  1693. proc bgerror {msg} {
  1694.     Say $msg
  1695. }
  1696.  
  1697. proc checkup {} {
  1698.     catch {noninteractive battery}
  1699.     after 10000 checkup
  1700. }
  1701.  
  1702. after 1000 checkup
  1703.  
  1704. proc checkupin {time} {
  1705.     after $time {catch {noninteractive battery}}
  1706. }
  1707.  
  1708. ",NULL);     
  1709.  
  1710.   Tcl_LinkVar(interp, "Interactive", (char*)&Interactive, TCL_LINK_INT);
  1711.  
  1712.  
  1713. #ifdef TK  
  1714.   if (usetk)
  1715.     Tcl_VarEval(interp,"inittkdbg",NULL);
  1716.   else
  1717.     Tcl_VarEval(interp,"set tkdbg 0", NULL);
  1718. #endif
  1719.  
  1720.   Say("\tWelcome to pilot-debug!\n\nType 'help' for further information.\n\n");
  1721.   
  1722. #if 0
  1723.   Say("\tWelcome to pilot-debug!\n\n\
  1724. Please connect your Pilot and start console or debugging mode.\n\n(Console mode is a background \
  1725. task that can respond to a few commands, most importantly RPC which lets any function on the \
  1726. Pilot be invoked. The Pilot operates as usual while console mode is active, except that \
  1727. since the serial port is help open, HotSync and other applications that use the serial port \
  1728. will not work. Debug mode is activated on demand or when the Pilot crashes. In debug mode, the \
  1729. CPU is halted, and no commands may be executed, except via a debugging console like this one.)\n\n\
  1730. In the absence of special utilities, the console can be started by \
  1731. the \".2\" shortcut, and debugging via \".1\". To clear either mode, \
  1732. reboot via the reset button. If console mode is active, you may \
  1733. also reboot via the \"coldboot\" or \"warmboot\" commands.\n\n\
  1734. The Remote UI window lets you manipulate the Pilot if console mode is active. By clicking the \
  1735. mouse button on the screen or buttons, you can simulate pen taps, and if you type anything \
  1736. while the window has the focus, the Pilot will receive the keystrokes.\n\n \
  1737. The Remote Console window is specifically for the transmission and reception of console \
  1738. packets. Pressing Return on a line will transmit it, and any incoming packets will be \
  1739. displayed here in addition to the Debug Console.\n\n\
  1740. The Remote State window shows the current Pilot CPU state. It is only updated on request or \
  1741. when the Pilot halts.\n\n\
  1742. The Debugging Console window is the primary interface for pilot-debug. Pressing Return on a \
  1743. line that contains text will execute that line as a Tcl command. (Try 'expr 3+4'.) All of \
  1744. the usual Tcl and Tk commands are available, as well as some special-purpose ones, including \
  1745. 'help', 'coldboot', 'warmboot', 'attach', 't', and 'g', (the last one continues after the Pilot halts.)\n\n\
  1746. Execute 'help' for the list of commands currently implemented.\n\
  1747. ");
  1748. #endif
  1749.  
  1750.     /*
  1751.      * Specify a user-specific startup file to invoke if the application
  1752.      * is run interactively.  Typically the startup file is "~/.apprc"
  1753.      * where "app" is the name of the application.  If this line is deleted
  1754.      * then no user-specific startup file will be run under any conditions.
  1755.      */
  1756.  
  1757.     Tcl_SetVar(interp, "tcl_rcFileName", "~/.pdebugrc", TCL_GLOBAL_ONLY);
  1758.  
  1759.     Tcl_VarEval(interp,"\
  1760.       set tcl_prompt1 myprompt
  1761.       proc myprompt {} {
  1762.         puts -nonewline \"pilot-debug> \"
  1763.       }
  1764.       
  1765.     ",NULL);
  1766.  
  1767.     /* Deal with command-line arguments */
  1768.  
  1769.     Tcl_VarEval(interp,"\
  1770.       if {$argc > 0} {
  1771.         set p [lindex $argv 0]
  1772.         set argv [lrange $argv 1 end]
  1773.         port $p
  1774.       } else {
  1775.         Say \"As you have not entered a serial port on the command like, you might like to \
  1776. set one with 'port /dev/something'\\n\\n\"
  1777.       }
  1778.     ",NULL);
  1779.         
  1780.     return TCL_OK;
  1781. }
  1782.  
  1783. int main(int argc, char *argv[])
  1784. {
  1785.     char *args, *fileName;
  1786.     char buf[20];
  1787.     int code;
  1788.     size_t length;
  1789.     int exitCode = 0;
  1790.     Tcl_Channel errChannel;
  1791.  
  1792.     Tcl_FindExecutable(argv[0]);
  1793.     interp = Tcl_CreateInterp();
  1794.  
  1795.     fileName = NULL;
  1796.     if (argc > 2) {
  1797.     length = strlen(argv[1]);
  1798.     if ((length >= 2) && (strncmp(argv[1], "-file", length) == 0)) {
  1799.         fileName = argv[2];
  1800.         argc-=2;
  1801.         argv+=2;
  1802.     }
  1803.     }
  1804.  
  1805. #ifdef TK    
  1806.     usetk = 1;
  1807. #endif
  1808.     
  1809.     if (argc > 1) {
  1810.         length = strlen(argv[1]);
  1811.         if ((length >= 2) && (strncmp(argv[1], "-notk", length) == 0)) {
  1812. #ifdef TK
  1813.              usetk = 0;
  1814. #endif
  1815.              argc--;
  1816.              argv++;
  1817.         }
  1818.     }
  1819.  
  1820.     /*
  1821.      * Make command-line arguments available in the Tcl variables "argc"
  1822.      * and "argv".
  1823.      */
  1824.  
  1825.     args = Tcl_Merge(argc-1, argv+1);
  1826.     Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
  1827.     ckfree(args);
  1828.     sprintf(buf, "%d", argc-1);
  1829.     Tcl_SetVar(interp, "argc", buf, TCL_GLOBAL_ONLY);
  1830.     Tcl_SetVar(interp, "argv0", (fileName != NULL) ? fileName : argv[0],
  1831.         TCL_GLOBAL_ONLY);
  1832.  
  1833.     /*
  1834.      * Set the "tcl_interactive" variable.
  1835.      */
  1836.  
  1837.     tty = isatty(0);
  1838.     Tcl_SetVar(interp, "tcl_interactive",
  1839.         ((fileName == NULL) && tty) ? "1" : "0", TCL_GLOBAL_ONLY);
  1840.  
  1841.  
  1842. #ifdef TK
  1843.     if (!getenv("DISPLAY") || (strlen(getenv("DISPLAY"))==0))
  1844.         usetk = 0;
  1845. #endif
  1846.  
  1847.     /*
  1848.      * Invoke application-specific initialization.
  1849.      */
  1850.  
  1851.     if (Tcl_AppInit(interp) != TCL_OK) {
  1852.     errChannel = Tcl_GetStdChannel(TCL_STDERR);
  1853.     if (errChannel) {
  1854.         Tcl_Write(errChannel,
  1855.             "application-specific initialization failed: ", -1);
  1856.         Tcl_Write(errChannel, interp->result, -1);
  1857.         Tcl_Write(errChannel, "\n", 1);
  1858.     }
  1859.     }
  1860.  
  1861.     /*
  1862.      * Invoke the script specified on the command line, if any.
  1863.      */
  1864.  
  1865.     if (fileName != NULL) {
  1866.     code = Tcl_EvalFile(interp, fileName);
  1867.     if (code != TCL_OK) {
  1868.         errChannel = Tcl_GetStdChannel(TCL_STDERR);
  1869.         if (errChannel) {
  1870.         /*
  1871.          * The following statement guarantees that the errorInfo
  1872.          * variable is set properly.
  1873.          */
  1874.  
  1875.         Tcl_AddErrorInfo(interp, "");
  1876.         Tcl_Write(errChannel,
  1877.             Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY), -1);
  1878.         Tcl_Write(errChannel, "\n", 1);
  1879.         }
  1880.         exitCode = 1;
  1881.     }
  1882.     goto done;
  1883.     }
  1884.  
  1885.    /* Tcl 7.5 did not support this command */
  1886. #if (TCL_MAJOR_VERSION > 7) || (TCL_MINOR_VERSION > 5)
  1887.  
  1888.     /*
  1889.      * We're running interactively.  Source a user-specific startup
  1890.      * file if the application specified one and if the file exists.
  1891.      */
  1892.  
  1893.     Tcl_SourceRCFile(interp);
  1894. #endif
  1895.     
  1896.     /*
  1897.      * Loop infinitely, waiting for commands to execute.  When there
  1898.      * are no windows left, Tk_MainLoop returns and we exit.
  1899.      */
  1900.      
  1901. #ifdef TK
  1902.     if (!usetk) {     
  1903. #endif
  1904.  
  1905.     /*
  1906.      * Process commands from stdin until there's an end-of-file.  Note
  1907.      * that we need to fetch the standard channels again after every
  1908.      * eval, since they may have been changed.
  1909.      */
  1910.  
  1911.     do_readline();
  1912.  
  1913.      
  1914. #ifdef TK
  1915.     }
  1916. #endif
  1917.  
  1918. done:
  1919.  
  1920. #ifdef TK
  1921.     if (usetk) {
  1922.         Tcl_VarEval(interp, ".f.t insert end {pilot-debug> }; .f.t set mark insert end",0);
  1923.         Tk_MainLoop();
  1924.         Tcl_DeleteInterp(interp);
  1925.         Tcl_Exit(0);
  1926.     }
  1927. #endif
  1928.     return 0;
  1929. }
  1930.  
  1931.